import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import OneHotEncoder

def model(x,theta):
    return x.dot(theta)

def sigmoid(z):
    return 1/(1+np.exp(-z))

def cost(h,y):
    m=len(h)
    J=- 1 / m * np.sum(np.sum(y * np.log(h), axis=1))
    return J

def 前向(x,theta1,theta2,theta3):
    z2=model(x,theta1)
    a2=sigmoid(z2)
    z3=model(a2,theta2)
    a3=sigmoid(z3)
    z4=model(a3,theta3)
    a4=sigmoid(z4)
    return a2,a3,a4

def 反向(x,y,theta1,theta2,theta3,a2,a3,a4,alpha):
    s4=a4-y
    s3=s4.dot(theta3.T)*(a3*(1-a3))
    s2=s3.dot(theta2.T)*(a2*(1-a2))

    m=len(y)
    dt3=1/m*a3.T.dot(s4)
    dt2=1/m*a2.T.dot(s3)
    dt1=1/m*x.T.dot(s2)

    theta3-=alpha*dt3
    theta2-=alpha*dt2
    theta1-=alpha*dt1
    return theta1,theta2,theta3
def 梯度下降(x,y,alpha=0.2,iter0=150):
    np.random.seed(123)
    m,n=x.shape
    theta1=np.random.randn(n,200)
    theta2=np.random.randn(200,200)
    ######################
    #10类
    theta3=np.random.randn(200,10)
    J=np.zeros(iter0)
    for i in range(iter0):
        a2,a3,a4=前向(x,theta1,theta2,theta3)
        J[i]=cost(a4,y)
        theta1,theta2,theta3=反向(x,y,theta1,theta2,theta3,a2,a3,a4,alpha)

    return a4,J,theta1,theta2,theta3
def 准确率(h,y):
    h_=np.argmax(h,axis=1)
    return np.mean(h_==y)

if __name__ == '__main__':
    #加载数据
    x=np.loadtxt('imgX.txt',delimiter=',')
    y=np.loadtxt('labely.txt',delimiter=',')
    #拼接
    X=np.c_[np.ones(len(x)),x]
    #将标签的10改成0
    y[y==10]=0
    #将标签独热处理
    y_onehot=np.zeros((len(y),10))
    for i in range(len(y)):
        y_onehot[i,int(y[i])]=1

    # print(y_onehot)
    #训练模型
    a4, J, theta1, theta2, theta3=梯度下降(X,y_onehot)
    plt.plot(J)
    print(J)
    plt.show()
    #准确率
    print(准确率(a4,y))